`include "../define.svh"
// 该模块用于检测输入是否为inf/nan，并直接将结果输出至out模块
module add_special_case (
    input [1:0] data_type,  // 2'b00:INT4,2'b01:INT8,2'b10:FP16,2'b11:FP32
    input [7:0] e1,
    input [7:0] e2,
    input s1, s2,
    input [23:0] m1,
    input [23:0] m2,
    output [7:0] e_out,
    output [22:0]m_out,
    output output_sign,      // 符号位输出
    output spec_valid        // valid信号，给下一级模块
);


    wire is_fp16, is_fp32;
    assign is_fp16 = (data_type == 2'b10);          // 类型判断
    assign is_fp32 = (data_type == 2'b11);
    wire op1_sub, op2_sub;
    assign op1_sub = is_fp16 ? ~m1[10] : ~m1[23];
    assign op2_sub = is_fp16 ? ~m2[10] : ~m2[23];

    wire [7:0]e1_correct,e2_correct;
    assign e1_correct = op1_sub ? 8'd0 : e1;
    assign e2_correct = op2_sub ? 8'd0 : e2;

    // 原有逻辑
    wire fp16_inf_flag_1, fp32_inf_flag_1, fp16_m_zero_1,fp32_m_zero_1;
    assign fp16_inf_flag_1 = (e1 == `FP16_INF_EXP); // 判断指数是否为inf
    assign fp32_inf_flag_1 = (e1 == `FP32_INF_EXP);
    assign fp16_m_zero_1 = (m1[9:0] == 10'd0);                // 判断尾数是否全0
    assign fp32_m_zero_1 = (m1[22:0] == 23'd0);                // 判断尾数是否全0

    wire fp16_inf_flag_2, fp32_inf_flag_2, fp16_m_zero_2,fp32_m_zero_2;
    assign fp16_inf_flag_2 = (e2 == `FP16_INF_EXP); // 判断指数是否为inf
    assign fp32_inf_flag_2 = (e2 == `FP32_INF_EXP);
    assign fp16_m_zero_2 = (m2[9:0] == 23'd0);                // 判断尾数是否全0
    assign fp32_m_zero_2 = (m2[22:0] == 23'd0);                // 判断尾数是否全0

    // 检测操作数是否为0（仅浮点类型）
    wire op1_zero = (is_fp16 && (e1 == 8'd0) &&fp16_m_zero_1) || 
                   (is_fp32 && (e1 == 8'd0) && fp32_m_zero_1);
    wire op2_zero = (is_fp16 && (e2 == 8'd0) && fp16_m_zero_2) || 
                   (is_fp32 && (e2 == 8'd0) && fp32_m_zero_2);
    wire single_zero = (op1_zero ^ op2_zero);  // 异或操作，仅一个为零时置1


    // Check for NaN and Inf in each operand
    wire op1_nan, op1_inf;
    assign op1_nan = (is_fp16 && fp16_inf_flag_1 && !fp16_m_zero_1) || 
                    (is_fp32 && fp32_inf_flag_1 && !fp32_m_zero_1); // 判断是否nan
    assign op1_inf = (is_fp16 && fp16_inf_flag_1 && fp16_m_zero_1) || 
                    (is_fp32 && fp32_inf_flag_1 && fp32_m_zero_1); // 判断是否inf

    wire op2_inf, op2_nan;
    assign op2_nan = (is_fp16 && fp16_inf_flag_2 && !fp16_m_zero_2) || 
                    (is_fp32 && fp32_inf_flag_2 && !fp32_m_zero_2); // 判断是否nan
    assign op2_inf = (is_fp16 && fp16_inf_flag_2 && fp16_m_zero_2) || 
                    (is_fp32 && fp32_inf_flag_2 && fp32_m_zero_2); // 判断是否inf
     
    wire sign_non_zero = op1_zero ? s2 : s1;
    wire [7:0] e_non_zero = op1_zero ? e2_correct : e1_correct;
    wire [22:0] m_non_zero = op1_zero ? m2[22:0] : m1[22:0];


    // 检测0×inf或inf×0的情况
    //wire zero_inf_case = (op1_zero && op2_inf) || (op2_zero && op1_inf);

    // Combined flags
    wire any_nan, both_inf, any_inf;
    assign any_nan = op1_nan || op2_nan;            // 输入中至少一个nan
    assign both_inf = op1_inf && op2_inf;           // 均为inf
    assign any_inf = (op1_inf || op2_inf) && !any_nan; // 至少一个inf

    // Check for opposite signs in Inf+Inf case
    wire inf_sign_diff;
    assign inf_sign_diff = both_inf && (s1 != s2);  // 异号inf相加时为NaN

    // Final result determination
    wire is_nan, is_inf;
    assign is_nan = any_nan || inf_sign_diff; // 新增zero_inf_case
    assign is_inf = any_inf && !inf_sign_diff;
    wire both_zero = op1_zero && op2_zero;

    // Calculate output sign for Inf cases（符号根据异或规则）
    assign output_sign = (single_zero) ? sign_non_zero : 
                        (both_zero) ? (s1 & s2) :  // 双零符号处理
                        (inf_sign_diff) ? (s1 ^ s2) : 
                        (both_inf) ? s1 : 
                        (op1_inf) ? s1 : s2;


    // Output assignments
    assign e_out = (single_zero) ? e_non_zero :  // 传递非零指数
              (is_nan || is_inf) ? 8'b11111111 : 
              (both_zero) ? 8'd0 : 8'd0;
    assign m_out = (single_zero) ? m_non_zero :  // 传递非零尾数
              (is_nan) ? 23'b1000000000000_10000_00000 : 
              (both_zero) ? 23'd0 : 23'd0;


    // valid信号
    assign spec_valid = is_nan || is_inf || both_zero || single_zero; // 单零需标记为有效

/*     always @(posedge clk or negedge sys_rst_n) begin
        if (!sys_rst_n) begin
            e_out_reg <= 0;
            m_out_reg <= 0;
        end else begin
            e_out_reg <= e_out;
            m_out_reg <= m_out;
        end
    end */

endmodule